﻿@namespace Masa.Blazor.Components.TemplateTable.SortDialogs
@inject I18n i18N

<PModal @bind-Value="Show"
        Width="640"
        Title="@i18N.T("Sorting")"
        Persistent
        BodyStyle="min-height: 180px"
        OnCancel="@HandleOnCancel"
        OnSave="@HandleOnSave">
    @for (var i = 0; i < _sorts.Count; i++)
    {
        var index = i;
        var option = _sorts[index];
        <div class="d-flex align-center justify-end mb-2">
            <div class="mr-2 text-right">
                @(index == 0 ? i18N.T("Sortby") : i18N.T("Thenby"))
                <span class="font-weight-bold">
                    @($"{option.Column.Name}({option.ColumnId})")
                </span>
            </div>

            <MSelect @bind-Value="@option.OrderBy"
                     Items="@_directions"
                     ItemValue="u => u.Value"
                     ItemText="@(u => i18N.T($"{u.Label}"))"
                     Class="mr-2"
                     Dense
                     Filled
                     HideDetails="@true"
                     Style="width: 160px; max-width: 160px;">
            </MSelect>

            @if (option.Persistent)
            {
                <div style="min-width: 36px;"></div>
            }
            else
            {
                <MButton IconName="mdi-close"
                         OnClick="@(() => RemoveSort(option))">
                </MButton>
            }
        </div>
    }

    @if (ComputedColumns.Count > 0)
    {
        <div class="text-right" style="margin-right: 44px;">
            <SortBy Columns="@ComputedColumns"
                    OnSelect="@AddSort">
                @(_sorts.Count == 0 ? i18N.T("Sortby") : i18N.T("Add"))
            </SortBy>
        </div>
    }

</PModal>

@code
{
    [Parameter] public IList<ColumnInfo> Columns { get; set; } = [];

    [Parameter] public HashSet<string> HiddenColumnIds { get; set; } = [];

    [Parameter] public View ActiveView { get; set; } = null!;

    [Parameter] public EventCallback<Sort> OnSave { get; set; }

    [Parameter] public bool Show { get; set; }

    [Parameter] public EventCallback<bool> ShowChanged { get; set; }

    private static (SortOrder Value, string Label)[] _directions =
    [
        (SortOrder.Asc, "ascending"),
        (SortOrder.Desc, "descending")
    ];

    private IList<ColumnInfo> _computedColumns = [];

    private IList<SortModel> _sorts = [];

    private IEnumerable<string> SortColumnIds => _sorts.Select(u => u.Column.Id);

    private IList<ColumnInfo> ComputedColumns => _computedColumns.Where(u => !SortColumnIds.Contains(u.Id)).ToList();

    private void SetSorts()
    {
        _computedColumns = Columns.Where(u => !HiddenColumnIds.Contains(u.Id)).Where(u => u.Type != ColumnType.Actions).ToList();

        _sorts.Clear();

        foreach (var option in ActiveView.Sort.Options.OrderBy(u => u.Index))
        {
            var column = Columns.FirstOrDefault(u => u.Id == option.ColumnId);
            if (column is null)
            {
                continue;
            }

            _sorts.Add(new SortModel(column, option.Index)
            {
                OrderBy = option.OrderBy,
                Type = option.Type,
                Persistent = option.Persistent
            });
        }
    }

    private int GetNextIndex()
    {
        return _sorts.MaxBy(u => u.Index)?.Index + 1 ?? 0;
    }

    internal void Open()
    {
        SetSorts();
        Show = true;
        StateHasChanged();
    }

    private void AddSort(Column column)
    {
        _sorts.Add(new SortModel(column, GetNextIndex()));
    }

    private void RemoveSort(SortModel model)
    {
        if (model.Persistent)
        {
            return;
        }

        _sorts.Remove(model);
    }

    private async Task HandleOnCancel()
    {
        _sorts.Clear();
        Show = false;
        if (ShowChanged.HasDelegate)
            await ShowChanged.InvokeAsync(Show);
    }

    private async Task HandleOnSave()
    {
        Show = false;
        if (ShowChanged.HasDelegate)
            await ShowChanged.InvokeAsync(Show);

        var sort = new Sort()
        {
            Options = _sorts.Select(u => u.ToSortOption()).ToList()
        };

        if (OnSave.HasDelegate)
            await OnSave.InvokeAsync(sort);
    }
}